package vn.edu.saigontech.ncms.web.offering;

import java.util.Date;
import java.util.Set;

import vn.edu.saigontech.ncms.model.enumeration.AttendanceStatus;
import vn.edu.saigontech.ncms.model.info.Offering;
import vn.edu.saigontech.ncms.model.info.OfferingMember;
import vn.edu.saigontech.ncms.model.studying.Attendance;
import vn.edu.saigontech.ncms.service.AttendanceService;
import vn.edu.saigontech.ncms.service.OfferingMemberService;
import vn.edu.saigontech.ncms.service.OfferingService;
import vn.edu.saigontech.ncms.util.Checker;
import vn.edu.saigontech.ncms.util.DateUtil;
import vn.edu.saigontech.ncms.web.BaseAction;
import vn.edu.saigontech.ncms.web.offering.report.CheckingAttendanceVO;

@SuppressWarnings("serial")
public class AttendanceAction extends BaseAction {

	private Long offeringId;
	private Long[] memberIds;
	private String fromDate;
	private String toDate;
	private String status;
	private String comment;
	
	private Long memberId;
	private String date;
	
	private int fromWeek;
	private int toWeek;
	
	private final double absentAllowPercent = 0.3;
	private final double hoursPerSession = 1.5;
	
	public String info() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		REQUEST().setAttribute("model", new CheckingAttendanceVO(offering, true));
		return SUCCESS;
	}
	
	public String showEdit() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		
		if(!Checker.isEmpty(this.date)) {
			REQUEST().setAttribute("selectedDate", DateUtil.fromString(this.date, this.i18n("format.date")));
		}
		REQUEST().setAttribute("offeringMember", OfferingMemberService.INSTANCE.findById(this.memberId));
		REQUEST().setAttribute("offeringMembers", OfferingMemberService.INSTANCE.findByOfferingId(this.offeringId, true));
		REQUEST().setAttribute("offering", offering);
		return SUCCESS;
	}
	
	public String edit() {	
		AttendanceStatus enumStatus = AttendanceStatus.valueOf(this.status);
		Date fromDateObject = DateUtil.fromString(this.fromDate, this.i18n("format.date"));
		Date toDateObject = DateUtil.fromString(this.toDate, this.i18n("format.date"));
		
		for(Long each : this.memberIds) {
			for(Date day : OfferingService.INSTANCE.findTeachingDays(this.offeringId, fromDateObject, toDateObject)) {
				Attendance attendance = AttendanceService.INSTANCE.findByOfferingMemberIdAndDate(each, day);
				if(Checker.isNull(attendance) && !AttendanceStatus.NONE.equals(enumStatus)) {
					AttendanceService.INSTANCE.add(each, day, AttendanceStatus.valueOf(this.status), this.comment);
				}
				else if (!Checker.isNull(attendance) && !AttendanceStatus.NONE.equals(enumStatus)){
					AttendanceService.INSTANCE.edit(attendance.getId(), day, AttendanceStatus.valueOf(this.status), this.comment);
				}
				else if (!Checker.isNull(attendance) && AttendanceStatus.NONE.equals(enumStatus)) {
					AttendanceService.INSTANCE.deleteAndFlush(attendance.getId());
				}
			}
		}
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		Set<OfferingMember> members = offering.getActiveMembers();
		for(OfferingMember member : members) {
			//calculate the real teaching days (not excludes the HOLIDAYS)
			//int totalSession = OfferingService.INSTANCE.findTeachingDays(this.offeringId).size();
			double totalSession = OfferingService.INSTANCE.findById(this.offeringId).getLevel().getHours() / hoursPerSession;
			int totalAbsence = member.getAbsentAttendances().size();
			double percent = (double) totalAbsence / totalSession;
			
			String reason = "nghỉ quá số buổi qui định";
			if(percent >= this.absentAllowPercent) {
				OfferingMemberService.INSTANCE.edit(member.getId(), false, reason);
			}
		}
		this.addLoggingDetail(BaseAction.EDIT, "logging.attendance.edit", offering.getName(), this.fromDate, this.toDate);
		return SUCCESS;
	}
	
	public String showReport() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		Date startDate = offering.getStartDate();
		Date endDate = offering.getEndDate();
		int startWeek = DateUtil.getWeekOfYear(startDate);
		int endWeek = DateUtil.getWeekOfYear(endDate);
		if(DateUtil.getYear(startDate) < DateUtil.getYear(endDate)) {
			startWeek = startWeek - 52;
		}
		int maxWeek = endWeek - startWeek + 1;
		if(maxWeek < 0)
			maxWeek = endWeek - startWeek + 1 + 52;
		REQUEST().setAttribute("maxWeek", maxWeek);
		REQUEST().setAttribute("offeringId", this.offeringId);
		return SUCCESS;
	}
	
	public String report() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		REQUEST().setAttribute("model", new CheckingAttendanceVO(offering, false));
		this.addLoggingDetail(BaseAction.REPORT, "logging.attendance.report", offering.getName());
		return SUCCESS;
	}
	
	public String reportWeekly() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		REQUEST().setAttribute("model", new CheckingAttendanceVO(offering, false, this.fromWeek, this.toWeek));
		this.addLoggingDetail(BaseAction.REPORT, "logging.attendance.weeklyReport", this.fromWeek, this.toWeek, offering.getName());
		return SUCCESS;
	}
	
	public void setOfferingId(Long offeringId) {
		this.offeringId = offeringId;
	}

	public Long[] getMemberIds() {
		return memberIds;
	}

	public void setMemberIds(Long[] memberIds) {
		this.memberIds = memberIds;
	}

	public String getFromDate() {
		return fromDate;
	}

	public void setFromDate(String fromDate) {
		this.fromDate = fromDate;
	}

	public String getToDate() {
		return toDate;
	}

	public void setToDate(String toDate) {
		this.toDate = toDate;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public Long getOfferingId() {
		return offeringId;
	}

	public String getComment() {
		return comment;
	}

	public void setComment(String comment) {
		this.comment = comment;
	}

	public Long getMemberId() {
		return memberId;
	}

	public void setMemberId(Long memberId) {
		this.memberId = memberId;
	}

	public String getDate() {
		return date;
	}

	public void setDate(String date) {
		this.date = date;
	}

	public int getFromWeek() {
		return fromWeek;
	}

	public void setFromWeek(int fromWeek) {
		this.fromWeek = fromWeek;
	}

	public int getToWeek() {
		return toWeek;
	}

	public void setToWeek(int toWeek) {
		this.toWeek = toWeek;
	}
}
